﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml;
using System.Web.Script.Services;
using ZEBuz.Questionnaire.Lib;
using ZEBuz.Questionnaire.Lib.Util;
using ZEBuz.Questionnaire.Lib.Entities;
using System.Data;

namespace ZEBuz.Questionnaire.Web
{
    /// <summary>
    /// Summary description for mainsvc
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class Mainsvc : System.Web.Services.WebService
    {
        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public string GetQuestionnaireData(string id)
        {
            serviceInit();

            XMLQuestionnaire qn = new Questionnaire.Lib.Entities.Questionnaire().Get(id.ToInt()).QuestionnaireDTO;
            //清除不需要用在界面上的元素，减少RESPONSE大小
            qn.categories = null;

            return qn.ToJSON();
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public int AddUserResultWithSignup(string email, string userName, string password,
            string sex, string age, string mage, string haschild, string answer, int questionnaireId)
        {
            string undefined = "undefined";
            int ret = -1;
            try
            {
                var user = new ZEBuz.Questionnaire.Lib.Entities.User();
                user.UserId = System.Guid.NewGuid().ToString();
                user.Age = age.ToInt();
                user.MarriageAge = mage.ToInt();
                user.Email = email == undefined ? string.Empty : email.Trim();
                user.HasChild = haschild == "1";
                user.Password = password;
                user.Sex = sex == undefined ? "U" : sex;
                user.Name = userName;
                user.Add();
                user.Logon(user);

                QuestionnaireUser qu = new QuestionnaireUser();
                qu.QuestionnaireId = questionnaireId;
                qu.UserAnswerString = answer;
                qu.UserId = user.UserId;

                ret = qu.Add();
            }
            catch (Exception ex)
            {
            }

            return ret;
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public int AddUserResultWithSignin(string email, string password, string userAnswer)
        {
            int ret = -1;
            try
            {
                var user = new ZEBuz.Questionnaire.Lib.Entities.User();
                user = user.Get(email, password);
                if (user != null && !string.IsNullOrEmpty(user.UserId))
                {
                    user.Logon(user);

                    QuestionnaireUser qu = new QuestionnaireUser();
                    qu.QuestionnaireId = 1;
                    qu.UserAnswerString = userAnswer;
                    qu.UserId = user.UserId;

                    ret = qu.Add();
                }
                else
                {
                    ret = -1; // 登陆失败
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return ret;
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public int AddUserResultWithCurrentUser(string userAnswer, int questionnaireId)
        {
            int ret = -1;
            try
            {
                dynamic user = System.Web.HttpContext.Current.Session["user"];
                if (user == null)
                {
                    ret = -2;
                }
                else
                {
                    QuestionnaireUser qu = new QuestionnaireUser();
                    qu.QuestionnaireId = questionnaireId;
                    qu.UserAnswerString = userAnswer;
                    qu.UserId = user.UserId;

                    ret = qu.Add();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return ret;
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public bool IsEmailAvailableForSignup(string email)
        {
            return !ZEBuz.Questionnaire.Lib.Entities.User.HasEmailForSignup(email);
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public bool IsMobileAvailableForSignup(string mobile)
        {
            return !ZEBuz.Questionnaire.Lib.Entities.User.HasMobileForSignup(mobile);
        }

        private string setReturnMsg(object msg)
        {
            return new { msg = msg as string }.ToJSON();
        }

        private readonly int m_iMaxForRptCompare = 5;

        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public string GetUserReport(int seqno)
        {
            return getUserReport(seqno.ToString());
        }

        /// <summary>
        /// for question table
        /// 支持多个SEQNO同时查看（最多5份），需要同一份问卷
        /// 样式：
        /// - 选项答案横排
        /// - 分区答案横排
        /// - 图表多个serials
        /// </summary>
        /// <param name="seqno"></param>
        /// <returns></returns>
        [WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        public string GetUserReportListWithAdmin(string seqnos)
        {
            //todo: check admin permission
            return getUserReport(seqnos.Trim());
        }

        #region Private Methods

        /// <summary>
        /// To validate whether user loginned
        /// </summary>
        /// <returns></returns>
        private bool serviceInit()
        {
            return true;
        }

        private string getUserReport(string seqnos)
        {
            var m_user = System.Web.HttpContext.Current.User;

            string[] list = seqnos.Split(',');

            #region Validation
            if (m_iMaxForRptCompare < list.Length) { return setReturnMsg("最多5份对比"); }
            if (list.Length <= 0) { return setReturnMsg("请选择用户！"); }
            #endregion Validation

            #region Declaration
            XMLQuestionnaire qn = null;
            var userOpts = new Dictionary<string, object[]>();
            var userResultsByCategory = new Dictionary<string, object[]>();
            var userCategoryValue = new Dictionary<string, int[]>(); // 用户ID, 用户分值数组
            List<int> seqnoList = new List<int>();

            list.ToList().ForEach(o =>
            {
                if (o.ToInt() > 0 && !seqnoList.Contains(o.ToInt()))
                {
                    seqnoList.Add(o.ToInt());
                }
            });

            #endregion Declaration

            #region Get data source
            QuestionnaireUser qu = new QuestionnaireUser();
            var qus = new List<KeyValuePair<int, QuestionnaireUser>>();
            List<string> userNames = new List<string>();

            foreach (int seqno in seqnoList)
            {
                // 生成类别下的用户答案数组
                qu = new QuestionnaireUser(seqno);
                if (qus.Count(o => o.Value.QuestionnaireId != qu.QuestionnaireId) >= 1)
                    return setReturnMsg("不是使用的同一份问卷,无法比较,请由正常途径选择用户进行对比。");

                if (qn == null) { qn = qu.Questionnaire.QuestionnaireDTO; }

                qus.Add(new KeyValuePair<int, QuestionnaireUser>(seqno, qu));

                userNames.Add(qu.User.Name);
            }


            foreach (var q in qn.questions)
            {
                List<object[]> arr = new List<object[]>();
                foreach (int seqno in seqnoList)
                {
                    var content = string.Empty;
                    if (qus.Count(o => o.Key == seqno) > 0
                        && qus.Find(o => o.Key == seqno).Value.UserAnswers.Count(o => o.Question.id == q.id) > 0)
                    {
                        content = qus.Find(o => o.Key == seqno).Value.UserAnswers.Find(o => o.Question.id == q.id).Option.content;
                    }
                    arr.Add(new string[] { seqno.ToString(), content });
                }
                userOpts.Add(q.id, arr.ToArray());
            }


            foreach (var c in qn.categories)
            {
                List<object[]> arr = new List<object[]>();
                foreach (int seqno in seqnoList)
                {
                    if (qus.Count(o => o.Key == seqno) > 0
                      && qus.Find(o => o.Key == seqno).Value.UserAnswerByCategories.Count(o => o.Category.id == c.id) > 0)
                    {
                        CategoryTotalPoint ctp = qus.Find(o => o.Key == seqno).Value.UserAnswerByCategories.Find(o => o.Category.id == c.id);
                        if (ctp != null)
                        {
                            arr.Add(
                                new object[] { seqno, 
                                    string.Format("您的得分为{0}:{1}", 
                                    ctp.UserOptionLevel.name, 
                                    ctp.UserOptionLevel.text) 
                                });
                        }
                    }
                }
                userResultsByCategory.Add(c.id, arr.ToArray());
            }

            foreach (int seqno in seqnoList)
            {
                List<int> arr = new List<int>();
                foreach (var c in qn.categories)
                {
                    CategoryTotalPoint ctp = qus.Find(o => o.Key == seqno).Value.UserAnswerByCategories.Find(o => o.Category.id == c.id);
                    arr.Add(ctp == null ? 0 : ctp.TotalPoint);
                }
                userCategoryValue.Add(seqno + "." + qus.Find(o => o.Key == seqno).Value.User.Name, arr.ToArray());
            }

            #endregion Get data source

            // prepare an anonymous object for JSON serialization 
            if (qn == null) return setReturnMsg("");

            var questionDoc =
                from q in qn.questions
                join a in userOpts
                on q.id equals a.Key
                select new
                {
                    q,
                    answer = a.Value
                };

            // uniformed as jQuery dataTables required
            var question = new
            {
                sEcho = 1,
                aaData = questionDoc.ToList().Select(
                        o => new object[] 
                        {
                            o.q.id,
                            o.q.category.name,
                            o.q.content,
                            o.answer
                        })
            };

            var resultDoc =
                from c in qn.categories
                from q in userResultsByCategory
                where c.id == q.Key
                select new
                {
                    Category = c,
                    result = q.Value
                };

            // uniformed as jQuery dataTables required
            var result = new
            {
                sEcho = 1,
                aaData = resultDoc.ToList().Select(
                o => new object[] 
                        {
                            o.Category.id,
                            o.Category.name,
                            o.Category.desc,
                            // 用户结论列表
                            o.result
                        })
            };

            var svcRet = new
            {
                u = userNames.Select(o => "用户" + o),

                // 问题表格（包含全部问题，及灵活可扩展的用户答案列）
                q = question,

                // 分类表格（包含全部分类，及灵活可扩展的用户结论列）
                a = result,

                // 图表中使用的分类数组
                chart_category = qn.categories.Select(o => o.name),

                // 图表中使用的答案系列二维数组，一维指向分类 [[1,2,3][4,5,6]]
                chart_serials = userCategoryValue.ToArray()
            };

            return svcRet.ToJSON();
        }
        #endregion
    }
}
